<template>
  <div class="question-container">
    <div class="page-header">
      <h2>题目管理</h2>
      <el-button type="primary" @click="handleCreate" :icon="Plus">新建题目</el-button>
    </div>

    <el-card>
      <div class="search-area">
        <el-form :inline="true" :model="searchForm" @submit.prevent="handleSearch">
          <el-form-item label="状态">
            <el-select v-model="searchForm.status" placeholder="请选择状态" clearable style="width: 120px;">
              <el-option label="已发布" :value="1"></el-option>
              <el-option label="待审核" :value="0"></el-option>
              <el-option label="已驳回" :value="-1"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="分类">
            <el-select v-model="searchL1CategoryId" placeholder="一级分类" clearable @change="handleSearchL1CategoryChange" style="width: 150px;">
              <el-option v-for="cat in l1CategoryOptions" :key="cat.id" :label="cat.name" :value="cat.id" />
            </el-select>
            <el-select v-model="searchForm.categoryId" placeholder="二级分类" clearable :disabled="!searchL1CategoryId" style="width: 150px; margin-left: 10px;">
              <el-option v-for="cat in searchL2CategoryOptions" :key="cat.id" :label="cat.name" :value="cat.id" />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSearch">搜索</el-button>
            <el-button @click="handleReset">重置</el-button>
          </el-form-item>
        </el-form>
      </div>

      <el-table :data="tableData" v-loading="loading" style="width: 100%">
        <el-table-column prop="id" label="ID" width="80" />
        <el-table-column prop="title" label="题目标题" show-overflow-tooltip />
        <el-table-column prop="type" label="类型" width="100">
          <template #default="scope">{{ getTypeText(scope.row.type) }}</template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="100">
          <template #default="scope">
            <el-tag v-if="scope.row.status === 1" type="success">已发布</el-tag>
            <el-tag v-if="scope.row.status === 0" type="warning">待审核</el-tag>
            <el-tag v-if="scope.row.status === -1" type="danger">已驳回</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="createName" label="创建人" width="120" />
        <el-table-column prop="createTime" label="创建时间" width="180" />
        <el-table-column label="分类" min-width="200">
          <template #default="scope">
            {{ getCategoryText(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200" fixed="right">
          <template #default="scope">
            <el-button v-if="userStore.userInfo.userRole === '0' && scope.row.status === 0" size="small" type="success"
              @click="handleApprove(scope.row)">审核</el-button>
            <el-button size="small" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button size="small" type="danger" v-if="userStore.userInfo.userRole === '0'"
              @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination-container">
        <el-pagination v-model:current-page="pagination.pageNum" v-model:page-size="pagination.pageSize"
          :page-sizes="[10, 20, 50, 100]" :total="pagination.total" layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange" @current-change="handleCurrentChange" />
      </div>
    </el-card>

        <!-- 新建/编辑对话框 -->
        <el-dialog
          v-model="dialogVisible"
          :title="dialogTitle"
          width="80%"
          top="5vh"
          class="question-dialog"
        >
          <el-form ref="formRef" :model="form" :rules="formRules" label-width="100px" label-position="top">
            <el-divider content-position="left">基本信息</el-divider>
            <el-row :gutter="20">
              <el-col :span="12" :xs="24">
                <el-form-item label="题目标题" prop="title">
                  <el-input v-model="form.title" placeholder="请输入题目标题" />
                </el-form-item>
              </el-col>
              <el-col :span="6" :xs="24">
                <el-form-item label="题目分类" prop="categoryId">
                  <div class="category-select-group">
                    <el-select
                      v-model="selectedL1CategoryId"
                      placeholder="请选择一级分类"
                      @change="handleL1CategoryChange"
                      class="category-select"
                    >
                      <el-option v-for="cat in l1CategoryOptions" :key="cat.id" :label="cat.name" :value="cat.id" />
                    </el-select>
                    <el-select
                      v-model="form.categoryId"
                      placeholder="请选择二级分类"
                      class="category-select"
                      :disabled="!selectedL1CategoryId"
                      clearable
                    >
                      <el-option v-for="cat in l2CategoryOptions" :key="cat.id" :label="cat.name" :value="cat.id" />
                    </el-select>
                  </div>
                </el-form-item>
              </el-col>
              <el-col :span="6" :xs="24">
                <el-form-item label="题目类型" prop="type">
                  <el-select v-model="form.type" placeholder="请选择类型" @change="handleTypeChange">
                    <el-option label="单选题" value="1" />
                    <el-option label="多选题" value="2" />
                    <el-option label="填空题" value="3" />
                    <el-option label="判断题" value="4" />
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>

        <el-divider content-position="left">题干内容 (可选)</el-divider>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="题目图片">
              <el-upload
                v-model:file-list="imageFileList"
                list-type="picture-card"
                :http-request="uploadRequest"
                :on-success="handleImageUploadSuccess"
                :on-remove="handleImageRemove"
                :on-preview="handlePictureCardPreview"
                 :before-upload="beforeImageUpload">
                <el-icon><Plus /></el-icon>
              </el-upload>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="题目视频">
              <el-upload
                v-model:file-list="videoFileList"
                list-type="picture-card"
                :http-request="uploadRequest"
                :on-success="handleVideoUploadSuccess"
                :on-remove="handleVideoRemove"
                 :before-upload="beforeVideoUpload">
                <template #file="{ file }">
                  <div class="custom-video-preview">
                    <!-- 自定义视频预览模板 -->
                    <video :src="file.url" class="el-upload-list__item-thumbnail" controls>
                      您的浏览器不支持 video 标签。
                    </video>
                    <span class="el-upload-list__item-actions">
                      <span class="el-upload-list__item-delete" @click="handleManualVideoRemove(file)">
                        <el-icon><Delete /></el-icon>
                      </span>
                    </span>
                  </div>
                </template>
                <el-icon><Plus /></el-icon>
              </el-upload>
            </el-form-item>
          </el-col>
        </el-row>

        <el-divider content-position="left">答案与选项</el-divider>
        <el-form-item prop="optionList">
          <QuestionOptionsEditor v-model:options="form.optionList" :question-type="form.type" />
        </el-form-item>

        <el-divider content-position="left">题目解析 (可选)</el-divider>
        <el-form-item prop="analysisList">
          <QuestionAnalysisEditor v-model:analysis="form.analysisList" />
        </el-form-item>

        <div v-if="userStore.userInfo.userRole === '0'">
          <el-divider content-position="left">其他设置</el-divider>
          <el-form-item label="状态" prop="status">
            <el-radio-group v-model="form.status">
              <el-radio :label="1">已发布</el-radio>
              <el-radio :label="0">待审核</el-radio>
              <el-radio :label="-1">驳回</el-radio>
            </el-radio-group>
          </el-form-item>
        </div>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit" :loading="submitLoading">
            确定
          </el-button>
        </span>
             </template>
     </el-dialog>

     <!-- 图片预览对话框 -->
     <el-dialog v-model="dialogPreviewVisible" title="图片预览" width="50%" append-to-body>
       <img :src="dialogImageUrl" style="width: 100%" alt="Preview Image" />
     </el-dialog>
   </div>
 </template>

<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
import { Plus, Delete } from '@element-plus/icons-vue'
import { pageQueryQuestionList, addQuestion, updateQuestion, deleteQuestion, auditQuestion } from '@/api/question'
import { pageQueryCategoryList as pageQueryCategoryListForCategory } from '@/api/category'
import { uploadFile } from '@/api/file'
import { useUserStore } from '@/store/modules/user'
import { ElMessage, ElMessageBox } from 'element-plus'
import QuestionOptionsEditor from './components/QuestionOptionsEditor.vue'
import QuestionAnalysisEditor from './components/QuestionAnalysisEditor.vue'

const userStore = useUserStore()
const loading = ref(false)
const submitLoading = ref(false)
const dialogVisible = ref(false)
const dialogTitle = ref('')

const formRef = ref()

const imageFileList = ref([])
const videoFileList = ref([])

const dialogImageUrl = ref('')
const dialogPreviewVisible = ref(false)

const tableData = ref([])
const allCategories = ref([]) // 所有分类数据
const selectedL1CategoryId = ref('') // Dialog用：一级分类 v-model
const searchL1CategoryId = ref('') // Search用: 一级分类 v-model

const pagination = reactive({
  pageNum: 1,
  pageSize: 10,
  total: 0
})

const searchForm = reactive({
  status: '',
  categoryId: '',
})

const initialFormState = () => ({
  id: null,
  title: '',
  categoryId: '',
  type: '1', // 默认单选
  status: 0, // 默认待审核
  videoList: [],
  imageList: [],
  optionList: [
    { optionContent: '', correctFlag: true, sort: 0 },
    { optionContent: '', correctFlag: false, sort: 1 }
  ],
  analysisList: []
})

const form = reactive(initialFormState())

const formRules = {
  title: [{ required: true, message: '请输入题目标题', trigger: 'blur' }],
  categoryId: [{ required: true, message: '请选择二级分类', trigger: 'change' }],
  type: [{ required: true, message: '请选择题目类型', trigger: 'change' }],
  optionList: [{ required: true, type: 'array', min: 1, message: '至少需要一个选项' }]
}

// 解析类型 映射：UI使用字符串，后端期望数字
const ANALYSIS_TYPE_MAP = { text: '1', image: '2', video: '3' }
const ANALYSIS_TYPE_REVERSE_MAP = { '1': 'text', '2': 'image', '3': 'video' }

// Helper to get text for display
const getTypeText = (type) => {
    const map = { '1': '单选', '2': '多选', '3': '填空', '4': '判断' }
    return map[type] || '未知';
}

const fetchList = async () => {
  loading.value = true
  try {
    const params = {
      pageNum: pagination.pageNum,
      pageSize: pagination.pageSize,
    }
     // 只添加有效的搜索条件
    if (searchForm.status !== '') {
      params.status = searchForm.status
    }
    if (searchForm.categoryId) {
      params.categoryId = searchForm.categoryId
    }

    const data = await pageQueryQuestionList(params)
    tableData.value = data.list || []
    pagination.total = data.total || 0
  } catch (error) {
    console.error('获取题目列表失败:', error)
  } finally {
    loading.value = false
  }
}

const fetchAllCategories = async () => {
  try {
    // 一次性获取所有分类用于级联选择
    const data = await pageQueryCategoryListForCategory({ pageNum: 1, pageSize: 999 })
    allCategories.value = data.list || []
  } catch (error)
  {
    console.error('获取类型列表失败:', error)
  }
}

// 计算一级分类选项
const l1CategoryOptions = computed(() => {
  return allCategories.value.filter(cat => cat.parentId === 0)
})

// 根据选择的一级分类，计算二级分类选项
const l2CategoryOptions = computed(() => {
  if (!selectedL1CategoryId.value) return []
  return allCategories.value.filter(cat => cat.parentId === selectedL1CategoryId.value)
})

// 计算搜索区域的二级分类选项
const searchL2CategoryOptions = computed(() => {
  if (!searchL1CategoryId.value) return []
  return allCategories.value.filter(cat => cat.parentId === searchL1CategoryId.value)
})

const categoryMap = computed(() => {
  return allCategories.value.reduce((map, cat) => {
    map[cat.id] = cat
    return map
  }, {})
})

const getCategoryText = (row) => {
  const first = categoryMap.value[row.firstCategoryId]
  const second = categoryMap.value[row.secondCategoryId]

  if (first && second) {
    return `${first.name} / ${second.name}`
  }

  if (second) {
    const parent = categoryMap.value[second.parentId]
    if (parent) {
      return `${parent.name} / ${second.name}`
    }
    return second.name
  }

  if (first) {
    return first.name
  }

  return '--'
}

onMounted(() => {
  fetchList()
  fetchAllCategories()
})

const handleCreate = () => {
  resetForm();
  dialogTitle.value = '新建题目'
  dialogVisible.value = true
}

const handleEdit = (row) => {
  resetForm()
  dialogTitle.value = '编辑题目'
  // Deep copy is important here
  const rowData = JSON.parse(JSON.stringify(row))

  selectedL1CategoryId.value = rowData.firstCategoryId || ''

  // Map list DTO to form DTO
  form.id = rowData.id
  form.title = rowData.title
  form.categoryId = rowData.secondCategoryId || ''
  form.type = rowData.type
  form.status = rowData.status
  // 列表返回的是单个 string，而提交需要 array，在此做兼容转换
  form.imageList = rowData.questionImage ? [rowData.questionImage] : [];
  form.videoList = rowData.questionVideo ? [rowData.questionVideo] : [];

  // 填充上传组件所需的文件列表
  imageFileList.value = form.imageList.map(url => ({ name: url, url: resolveStaticUrl(url), relativeUrl: url }));
  videoFileList.value = form.videoList.map(url => ({ name: url, url: resolveStaticUrl(url), relativeUrl: url }));
  // 将后端返回的数值型解析类型转换为编辑器使用的字符串类型
  form.analysisList = (rowData.analysisList || []).map((item, index) => ({
      ...item,
      type: ANALYSIS_TYPE_REVERSE_MAP[String(item.type)] || item.type,
      sort: typeof item.sort === 'number' ? item.sort : index,
  }))

  // Use questionOptionList with correctFlag directly
  form.optionList = (rowData.questionOptionList || []).map((opt, index) => {
      return { ...opt, sort: index };
  });

  dialogVisible.value = true
}

const handleTypeChange = (newType) => {
  if (newType === '4') {
    form.optionList = [
      { optionContent: '正确', correctFlag: true, sort: 0 },
      { optionContent: '错误', correctFlag: false, sort: 1 },
    ]
  } else if (newType === '3') {
    form.optionList = [
      { optionContent: '', correctFlag: true, sort: 0 },
    ]
  } else {
    form.optionList = [
      { optionContent: '', correctFlag: true, sort: 0 },
      { optionContent: '', correctFlag: false, sort: 1 },
    ]
  }
}

const staticEndpoint = (import.meta.env.VITE_STATIC_ENDPOINT || '').replace(/\/$/, '');
const resolveStaticUrl = (value) => {
  if (!value) return '';
  if (/^https?:\/\//i.test(value) || value.startsWith('//')) return value;
  const normalizedPath = value.startsWith('/') ? value : `/${value}`;
  return `${staticEndpoint}${normalizedPath}`;
};

const uploadRequest = async (options) => {
  const { file } = options
  const formData = new FormData()
  formData.append('file', file)
  // 返回 axios 调用结果，交由组件触发 on-success/on-error
  return uploadFile(formData)
}

const beforeImageUpload = (rawFile) => {
  const isImage = ['image/jpeg', 'image/png', 'image/gif'].includes(rawFile.type)
  if (!isImage) {
    ElMessage.error('图片格式必须是 JPG/PNG/GIF 格式!')
    return false
  }
  const isLt10M = rawFile.size / 1024 / 1024 <= 10
  if (!isLt10M) {
    ElMessage.error('图片大小不能超过 10MB!')
    return false
  }
  return true
}
 
const beforeVideoUpload = (rawFile) => {
  // const isVideo = ['video/mp4', 'video/webm', 'video/ogg'].includes(rawFile.type)
  // if (!isVideo) {
  //   ElMessage.error('视频格式必须是 MP4/WEBM/OGG 格式!')
  //   return false
  // }
  return true
}

// 通过 uploadFiles 参数获取组件内部最新的文件列表，从而更新 form 中的数据
const handleImageUploadSuccess = (response, uploadFile, uploadFiles) => {
  ElMessage.success('图片上传成功');
  // 手动设置预览 URL，以便 el-upload 组件能正确显示刚上传的图片
  uploadFile.url = resolveStaticUrl(response);
  // 保存原始相对路径用于发送给后端，不使用resolveStaticUrl处理
  form.imageList = uploadFiles.map(file => {
    // 如果是新上传的文件，file.response是后端返回的相对路径
    // 如果是编辑时的文件，可能是原始的相对路径
    return file.response || file.relativeUrl || file.url;
  });
  // 打印图片
  console.log(form.imageList);
}

const handlePictureCardPreview = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url
  dialogPreviewVisible.value = true
}

const handleImageRemove = (uploadFile, uploadFiles) => {
  // 当文件被移除时，uploadFiles 已经是更新后的列表
  form.imageList = uploadFiles.map(file => file.response || file.relativeUrl);
}

const handleManualVideoRemove = (uploadFile) => {
  // 从数据层面手动移除文件
  const index = videoFileList.value.findIndex(file => file.uid === uploadFile.uid);
  if (index !== -1) {
    videoFileList.value.splice(index, 1);
    // 手动调用 on-remove 的逻辑来同步 form.videoList
    handleVideoRemove(uploadFile, videoFileList.value);
  }
}

const handleVideoUploadSuccess = (response, uploadFile, uploadFiles) => {
  ElMessage.success('视频上传成功');
  // 手动设置预览 URL，以便 el-upload 组件的自定义插槽能获取到视频地址
  uploadFile.url = resolveStaticUrl(response);
  form.videoList = uploadFiles.map(file => file.response || file.relativeUrl);
  // 打印视频
  console.log(form.videoList);
}

const handleVideoRemove = (uploadFile, uploadFiles) => {
  // 当文件被移除时，uploadFiles 已经是更新后的列表
  form.videoList = uploadFiles.map(file => file.response || file.relativeUrl);
}



const handleSubmit = async () => {
  if (!formRef.value) return
  
  try {
    await formRef.value.validate()
    submitLoading.value = true
    
    const payload = { ...form }
    // 选项排序
    payload.optionList = (form.optionList || []).map((opt, index) => ({ ...opt, sort: index }))
    // 解析列表：排序并转换类型为后端的数值编码
    payload.analysisList = (form.analysisList || []).map((item, index) => ({
        ...item,
        sort: index,
        type: ANALYSIS_TYPE_MAP[item.type] || String(item.type),
    }))

    // 提交时，对imageList和videoList进行脏数据处理，确保只发送相对路径
    // 去除可能包含的VITE_STATIC_ENDPOINT前缀
    const staticEndpoint = (import.meta.env.VITE_STATIC_ENDPOINT || '').replace(/\/$/, '');
    payload.imageList = (form.imageList || []).map(url => {
      if (!url) return url;
      // 如果URL包含VITE_STATIC_ENDPOINT前缀，则去除它
      if (staticEndpoint && url.startsWith(staticEndpoint)) {
        return url.substring(staticEndpoint.length);
      }
      return url;
    });
    payload.videoList = (form.videoList || []).map(url => {
      if (!url) return url;
      // 如果URL包含VITE_STATIC_ENDPOINT前缀，则去除它
      if (staticEndpoint && url.startsWith(staticEndpoint)) {
        return url.substring(staticEndpoint.length);
      }
      return url;
    });

    if (payload.id) {
      // 根据后端要求，更新操作不应传递 status
      delete payload.status;
      payload.questionId = payload.id;
      await updateQuestion(payload)
      ElMessage.success('更新成功')
    } else {
      // 会员用户发布的题目默认是待审核状态
      if (userStore.userInfo.userRole !== '0') {
          payload.status = 0;
      }
      await addQuestion(payload)
      ElMessage.success('创建成功，等待审核')
    }
    
    dialogVisible.value = false
    fetchList()
  } catch (error) {
    console.error('操作失败:', error)
  } finally {
    submitLoading.value = false
  }
}

const handleDelete = (row) => {
  ElMessageBox.confirm(
    `确定要删除题目 "${row.title}" 吗?`, 
    '警告',
    { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
  ).then(async () => {
    try {
      await deleteQuestion({ questionId: row.id })
      ElMessage.success('删除成功')
      fetchList()
    } catch (error) {
      console.error('删除失败:', error)
    }
  })
}

const handleApprove = async (row) => {
    // Show a mini-dialog for approve/reject
    ElMessageBox.confirm(`审核题目: "${row.title}"`, '审核', {
        distinguishCancelAndClose: true,
        confirmButtonText: '通过',
        cancelButtonText: '驳回',
    }).then(async () => {
        await auditQuestion({ questionId: row.id, status: 1 });
        ElMessage.success("已审核通过");
        fetchList();
    }).catch(async (action) => {
        if(action === 'cancel') { // 'cancel' means the '驳回' button was clicked
            await auditQuestion({ questionId: row.id, status: -1 });
            ElMessage.warning("已驳回");
            fetchList();
        }
    });
}

const handleSearch = () => {
  pagination.pageNum = 1
  fetchList()
}

const handleReset = () => {
  searchForm.status = ''
  searchForm.categoryId = ''
  searchL1CategoryId.value = ''
  pagination.pageNum = 1
  fetchList()
}

const handleSizeChange = (val) => {
  pagination.pageSize = val
  pagination.pageNum = 1
  fetchList()
}

const handleCurrentChange = (val) => {
  pagination.pageNum = val
  fetchList()
}

const resetForm = () => {
  if (formRef.value) {
    formRef.value.resetFields()
  }
  Object.assign(form, initialFormState())
  imageFileList.value = []
  videoFileList.value = []
  selectedL1CategoryId.value = ''
}

const handleL1CategoryChange = () => {
  // 当一级分类变化时，清空二级分类的选择
  form.categoryId = ''
}

const handleSearchL1CategoryChange = () => {
  // 当搜索区的一级分类变化时，清空二级分类
  searchForm.categoryId = ''
}

</script>

<style scoped>
.question-container {
  padding: 20px;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.page-header h2 {
  margin: 0;
  color: #333;
}

.search-area {
  margin-bottom: 20px;
}

.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: center;
}

 .dialog-footer {
   display: flex;
   justify-content: flex-end;
   gap: 10px;
 }

/* 自定义视频预览样式 */
.custom-video-preview {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.custom-video-preview .el-upload-list__item-actions {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  cursor: default;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  opacity: 0;
  font-size: 20px;
  background-color: rgba(0, 0, 0, 0.5);
  transition: opacity var(--el-transition-duration);
}
.custom-video-preview:hover .el-upload-list__item-actions {
  opacity: 1;
}
.custom-video-preview .el-upload-list__item-actions span {
  cursor: pointer;
}
 </style>
